"use client";
import {
  Button,
  Form,
  Input,
  Modal,
  Space,
  Table,
  message,
  type TableProps,
  Select,
  Radio,
  DatePicker,
} from "antd";
import { useCallback, useEffect, useRef, useState } from "react";
import { cloneDeep } from "lodash-es";
import React from "react";
import { ActionResponse } from "@/lib/handlerAction";
import { usePathname, useRouter, useSearchParams } from "next/navigation";
import { getSearchQuery, navUrl } from "@/lib/UrlTool";
import UploadOne from "./UploadOne";
import NumUploadFile from "./UploadNums";
import dayjs from "dayjs";
const { RangePicker } = DatePicker;
type SlotType = "headerSlot" | "formSlot" | "tableHeaderSlot";
export type FormType = "input" | "select" | "image" | "uploadNum" | "radio" | 'timerange';
export type SearchType = {
  value: string;
  label: string;
  type: FormType;
  fieldKey?: string;
  options?: {
    label: string;
    value: string;
  }[];
};
export type FixedType = 'left' | 'right' | boolean;

export type ColumnType = {
  title: string;
  key: string;
  dataIndex?: string;
  align?: "center" | "left" | "right";
  fixed?: FixedType;
  width?: number;
  /**
   * 是否在编辑显示按钮
   */
  showEdit?: boolean;
  formParams?: {
    type: FormType;
    mode?: undefined | "multiple" | "tags";
    isLoading?: boolean;
    options?: {
      label: string;
      value: string;
    }[];
    rules?: {
      required: boolean;
      message: string;
    }[];
    funOption?: () => Promise<
      {
        label: string;
        value: string;
      }[]
    >;
  };
  render?: (text: any, record: any, index: number) => React.ReactNode;
};
type XtableProps = {
  columns: ColumnType[];
  modalColumns?: ColumnType[];
  searchForm?: SearchType[];
  toolHeight?: number;
  tableX?: number;
  actionWidth?: number;
  actionSlot?: (row: any) => React.ReactNode;
  create?: (params: any) => Promise<ActionResponse<any>>;
  children?: React.ReactNode;
  deleteItem?: (params: any) => Promise<ActionResponse<any>>;
  update?: (params: any) => Promise<ActionResponse<any>>;
  getList: (params: any) => Promise<
    ActionResponse<{
      list: any;
      total: number;
    }>
  >;
};
const XTable = ({
  columns,
  children,
  create,
  deleteItem,
  getList,
  searchForm,
  update,
  modalColumns,
  actionSlot,
  tableX = 800,
  actionWidth = 0,
  toolHeight = 120,
}: XtableProps) => {

  const [data, setData] = useState<any[]>([]);
  const [loading, setLoading] = useState(true);
  const router = useRouter();
  const modalColumnsRef = useRef(modalColumns || []);
  const currentColumns = useRef(
    columns.map((it) => {
      if (!it.align) {
        it.align = "center";
      }

      return it;
    })
  );
  const currentSearchColumns = useRef(searchForm);
  const pathname = usePathname();
  const search = useSearchParams();

  // 插槽的使用
  const childSlots: Record<SlotType, React.ReactNode> = React.Children.toArray(children).reduce((pre: any, cu: any) => {
    pre[cu.props.name] = cu
    return pre
  }, {});

  let currentRow: any = useRef(null);
  if (update || deleteItem || actionSlot) {
    const index = currentColumns.current.findIndex((it) => it.key == "action");

    if (index === -1) {
      currentColumns.current.push({
        title: "操作",
        key: "action",
        showEdit: false,
        align: "center",
        fixed: "right",
        width: actionWidth,
        render: (text, record, index) => {
          return (
            <Space>
              <Button size="small" type='primary' onClick={() => showModal(record)}>
                编辑
              </Button>

              {deleteItem && <Button type='dashed' danger size="small" onClick={() => {
                Modal.confirm({
                  title: "确定删除吗？",
                  content: "删除后将无法恢复",
                  onOk: async () => {

                    const result = await deleteItem(record)
                    if (result.data) {
                      router.push(pathname + `?timestemp=${new Date().getTime()}`);
                      message.success("删除成功")
                    } else {
                    }
                  },
                });
              }} >删除</Button>}
              {actionSlot && actionSlot(record)}
            </Space>
          );
        },
      });

    }
  }
  const setColumns = async () => {
    for (let i = 0; i < currentColumns.current.length; i++) {
      const column = currentColumns.current[i];

      if (!column.render) {
        column.dataIndex = column.key;
      }
      if (column.formParams?.funOption && !column.formParams.isLoading && !column.formParams.options) {
        column.formParams.isLoading = true;
        column.formParams.options = await column.formParams.funOption();
      }
    }
    // 初始化 modal数据
    for (let i = 0; i < modalColumnsRef.current.length; i++) {
      const column = modalColumnsRef.current[i];

      if (!column.render) {
        column.dataIndex = column.key;
      }
      if (column.formParams?.funOption && !column.formParams.isLoading && !column.formParams.options) {
        column.formParams.isLoading = true;
        column.formParams.options = await column.formParams.funOption();
      }
    }
    // 初始化search数据
    const selectObj = currentColumns.current.reduce((it, cu: ColumnType) => {
      if (cu.formParams?.type === "select") {
        it[cu.key] = cu.formParams.options;
      }
      return it;
    }, {} as any);
    currentSearchColumns.current = currentSearchColumns.current?.map((it) => {
      if (it.type === "select" && it.fieldKey) {
        it.options = [
          {
            label: "全部",
            value: "",
          },
          ...selectObj[it.fieldKey],
        ];
      }
      return it;
    });
  };

  const [form] = Form.useForm();
  const [searchFormInstance] = Form.useForm();
  const [pageConfig, setPageConfig] = useState({
    current: search.get("page") ? Number(search.get("page")) : 1,
    total: 0,
    pageSize: search.get("pageSize") ? Number(search.get("pageSize")) : 10,
  });

  const fetchData = () => {
    if (getList) {
      const { current, pageSize } = pageConfig;
      getList({
        page: current,
        pageSize: pageSize,
        ...Object.fromEntries(search.entries()),
      }).then((res) => {
        // console.log(res.data);
        if (res.data) {
          setLoading(false);
          setData(res.data.list);
          setPageConfig({
            ...pageConfig,
            total: res.data.total,
          });
        } else {
          message.error(res.message)
        }
      });
    }
  };
  // 弹框控制
  const [isModalOpen, setIsModalOpen] = useState(false);

  const showModal = (item?: any) => {
    setIsModalOpen(true);

    if (item) {
      item = cloneDeep(item);
      currentRow.current = item;
      form.setFieldsValue(cloneDeep(item));
    } else {
      currentRow.current = null;
    }
  };

  const handleCancel = () => {
    setIsModalOpen(false);
    form.resetFields();
  };

  let defaultSearch = getSearchQuery(search)

  // setColumns()
  useEffect(() => {
    setColumns().then(() => {
      fetchData();
    });
  }, [search]);
  const onFinish = async (value: any) => {
    console.log(value);
    let fun = create;
    let params = cloneDeep(value);
    if (currentRow.current && update) {
      fun = update;
      params.id = currentRow.current.id;
    }
    const result = await fun!(params);
    if (result.code === 0) {
      message.success("操作成功");
      fetchData();
      handleCancel();
    } else {
      Modal.error({ title: "提示", content: result.message });
    }
  };
  const toSearch = () => {
    const searchValue = searchFormInstance.getFieldsValue()
    Object.keys(searchValue).forEach((key) => {
      const val = searchValue[key]
      if (searchValue[key] === undefined) {
        delete searchValue[key];
      }
      if (searchValue[key] instanceof dayjs) {
        searchValue[key] = dayjs(searchValue[key] as string).format("YYYY-MM-DD")
      }
      if (val instanceof Array) {
        if (val[0] instanceof dayjs) {
          searchValue[key] = val.map(it => dayjs(it as string).format("YYYY-MM-DD")).join('_')
        }
      }
    })
    navUrl(
      router,
      pathname,
      search,
      searchValue,
      (query:any) => {
        query.set('page',1)
        return query;
      }
    );
  };
  const searchReset = () => {
    let resetField = currentSearchColumns.current?.reduce((it, pre) => {
      it[pre.value] = undefined;
      return it;
    }, {} as any);
    searchFormInstance.setFieldsValue(resetField);
    router.push(pathname);
  };
  const tableRef = useCallback((node: HTMLDivElement) => {
    if (node !== null) {
      const height = node.clientHeight;
      setTableY(height - toolHeight);
    }
  }, []);
  const [tableY, setTableY] = useState(600);
  if (loading) {
    return <div className="flex w-full h-[50vh] items-center justify-center">isLoading...</div>;
  }

  return (
    <div className="h-[100%] x_table flex flex-col overflow-hidden">
      <div className="search-top pt-4 px-4 bg-white m-2 shadow-md rounded-md">
        <Form
          onFinish={toSearch}
          initialValues={defaultSearch || {}}
          form={searchFormInstance}
          layout="inline"
        >
          {currentSearchColumns.current && currentSearchColumns.current.length > 0 &&
            currentSearchColumns.current.map((it) => {
              if (it.type === "select") {
                return (
                  <Form.Item label={it.label} name={it.value} key={it.value}>
                    <Select
                      style={{ width: "200px" }}
                      options={it.options || []}
                    />
                  </Form.Item>
                );
              }
              if (it.type === 'timerange') {
                return <Form.Item label={it.label} name={it.value} key={it.value}>
                  <RangePicker />
                </Form.Item>
              }

              return (
                <Form.Item label={it.label} name={it.value} key={it.value} style={{ marginBottom: '16px' }}>
                  <Input />
                </Form.Item>
              );
            })}

          <Form.Item style={{ marginBottom: '16px' }}>
            <Space>
              <Button onClick={searchReset}>
                重置
              </Button>
              <Button type="primary" htmlType="submit">
                搜索
              </Button>
              {update && <Button type="primary" onClick={() => showModal()}>
                新增
              </Button>}
              {childSlots.headerSlot}
            </Space>
          </Form.Item>
        </Form>
      </div>
      <div className="flex-1 overflow-y-scroll" ref={tableRef}>
        {childSlots.tableHeaderSlot}
        <Table
          bordered
          columns={currentColumns.current}
          scroll={{ x: tableX, y: tableY }}
          pagination={{
            position: ["bottomCenter"],
            current: pageConfig.current,
            pageSize: pageConfig.pageSize,
            total: pageConfig.total,
            showSizeChanger: true,
            showTotal: (total) => `共 ${total} 条`,

            onChange(page, pageSize) {
              if (pageSize != pageConfig.pageSize) {
                pageConfig.current = 1;
              } else {
                pageConfig.current = page;
              }
              pageConfig.pageSize = pageSize;

              navUrl(
                router,
                pathname,
                search,
                {
                  pageSize,
                },
                (query) => {
                  query.set("page", pageConfig.current.toString());
                  return query;
                }
              );
              // fetchData()
            },
          }}
          rowKey="id"
          dataSource={data}
        ></Table>
      </div>

      {/* 新增dialog */}
      <Modal
        title="编辑"
        open={isModalOpen}
        onCancel={handleCancel}
        footer={null}
        maskClosable={false}
        width="70%"
      >
        <Form
          onFinish={onFinish}
          form={form}
          labelCol={{ span: 4 }}
          wrapperCol={{ span: 20 }}
        >
          {modalColumnsRef.current
            .map((it) => {
              return (
                <Form.Item
                  label={it.title}
                  name={it.key}
                  rules={it.formParams?.rules}
                  key={it.title}
                >
                  {it.formParams?.type === "select" && (
                    <Select
                      mode={it.formParams?.mode}
                      options={it.formParams.options || []}
                    />
                  )}
                  {it.formParams?.type === "image" && <UploadOne></UploadOne>}
                  {it.formParams?.type === "input" && <Input></Input>}
                  {it.formParams?.type === "uploadNum" && (
                    <NumUploadFile></NumUploadFile>
                  )}
                  {it.formParams?.type === "radio" && (
                    <Radio.Group>
                      {it.formParams?.options?.map((item: any) => {
                        return (
                          <Radio value={item.value} key={item.value}>
                            {item.label}
                          </Radio>
                        );
                      })}
                    </Radio.Group>
                  )}
                </Form.Item>
              );
            })}
          {childSlots.formSlot}
          <Form.Item
            wrapperCol={{ span: 24 }}
            className="flex justify-end w-full"
          >
            <Button className="mr-4" onClick={handleCancel}>
              取消
            </Button>
            <Button type="primary" htmlType="submit">
              确定
            </Button>
          </Form.Item>
        </Form>
      </Modal>
    </div>
  );
};


// eslint-disable-next-line react/display-name
XTable.Slot = ({ children }: { name: SlotType; children: React.ReactNode }) => {
  return children;
};
// XTable.Slot.displayName = "slot";
export default XTable;
